package world.square;

import java.math.BigDecimal;

import world.edges.Border;
import world.edges.Door;
import world.edges.Wall;
import world.placement.Direction;
import be.kuleuven.cs.som.annotate.Model;
import be.kuleuven.cs.som.annotate.Raw;

/**
 * Class representing a transparent square. 
 * A transparent square is not bordered by walls. It is bordered by at least one and maximum two doors.
 * 
 * @author Wim Marynissen, Frederic Mes
 * @version 1.0
 */
public class Transparent extends Square{
	
	/**
     * Create a new transparent square.
     * 
     * @effect 	This new transparent is initialized.
     *          | super(temperature, humidity, directions)
     * @post	Doors are added in the specified directions
     * 			| for each direction in directions:
     * 			|	(new this).getBorders().contains(direction)
     * 			|		&& getBorder(direction).getBorderElement() instanceof Door
     */
    public Transparent(Temperature temperature, BigDecimal humidity,Direction... directions) throws IllegalArgumentException {
    	super(temperature, humidity);
    	if (directions!= null)
			for(Direction direction : directions)
				addBorders(new Border(new Door(true), direction));
    }
    
    /**
     * Create a new standard transparent square.
     * 
     * @effect 	Initialization with standard square characteristics.
     *          | super()
     * @post	A door is added in the northern direction.
     * 			| (new this).getBorders().containts(Direction.NORTH)
     * 			|		&& getBorder(Direction.NORTH).getBorderElement() instanceof Door
     */
	public Transparent(){
		super();
		this.addBorders(new Border(new Door(false),Direction.NORTH));
	}
	
	/**
	 * Get the maximum number of doors.
	 */
	@Override
	public int maxNbDoors(){
		return 2;
	}
	
	/**
	 * Test if the square can have a certain border.
	 * @param 	border
	 * 			The border to check.
	 * @return	False if the border is a wall.
	 * 			| if(border != null)
	 * 			| 	if( !isTerminated() && !(border.getBorderElement() instanceof Wall) )
	 * 			| 		then result == false
	 * @return	If there's already one door, the new door must either replace the old one
	 * 			or be placed at the opposite position of the old one.
	 * 			| if(border != null)
	 * 			| 	if(countDoors() == 1)
	 * 			| 		then result == getDoor(1).getDirection().equals(border.getDirection().getOpposite())
	 * 			|							|| getDoor(1).getDirection().equals(border.getDirection())
	 * @effect	Test if the transparent square can have the specified border, considering it as a square.
	 * 			| super.canHaveAsBorder(border)
	 */
	@Raw
	@Override
    public boolean canHaveAsBorder(Border border){
		if(border != null){
            if( !isTerminated() && (border.getBorderElement() instanceof Wall) )
                    return false;
            if(countDoors() == 1)
            	return getDoor(1).getDirection().equals(border.getDirection().getOpposite())
            				|| getDoor(1).getDirection().equals(border.getDirection());
            	
		}
        return super.canHaveAsBorder(border); 
    }
	
	/**
	 * Returns a door bordering the square, if there are any.
	 * @param 	doorNb
	 * 			Number to indicate which door to return, if there are two.
	 * @return	The returned result is a door.
	 * 			| result instanceof Door
	 * @return	The result is either a border of this square, or null.
	 * 			| getBorders().contains(result) || (result == null)
	 */
	@Model
	private Border getDoor(int doorNb){
		for (Direction direction : Direction.values()){
			if(getBorder(direction) != null)
				if(getBorder(direction).getBorderElement() instanceof Door)
					doorNb--;
					if(doorNb == 0)
						return getBorder(direction);
		}
		return null;
	}
	
	/**
	 * Test if the border in the specified direction is proper.
	 * @param 	direction
	 * 			The direction in which to verify the border
	 * @return	False if the border is non-effective.
	 * 			| if(getBorder(direction) == null)
	 * 			| 	then result == true
	 * @return	True if the rock has been terminated.
	 * 			| if(this.isTerminated())
	 * 			| 	then result == true
	 * @return	The border must be a door, and must reference back to this transparent square..
	 * 			| 	result ==((getBorder(direction).getSquare() == this)
	 * 			|		&& (getBorder(direction).getBorderElement() instanceof Door))
	 */
	@Override
	public boolean hasProperBorder(Direction direction){
		if((getBorder(direction) != null) && !this.isTerminated){
			return ((getBorder(direction).getSquare() == this)
							&& (getBorder(direction).getBorderElement() instanceof Door));
		}
		return true;
		
	}
	/**
	 * Test if all of the borders are proper borders.
	 * @return	If there are two doors, they should be on opposite sides.
	 * 			| if( (countDoors() == 2)
	 *			|		&& !getDoor(1).getDirection()
	 *			|				.equals(getDoor(2).getDirection().getOpposite()))
	 *			|	then result == false
	 * @effect	Test the borders are valid for a square.
	 * 			| super.hasProperBorders()
	 */
	@Raw
	@Override
    public boolean hasProperBorders(){  
        if(countDoors() == 2){
        	if(!getDoor(1).getDirection().equals(getDoor(2).getDirection().getOpposite()))
        		return false;
        }
        return super.hasProperBorders();    
    }
}
